package gui;

import java.awt.Dimension;
import java.lang.reflect.Constructor;

import org.geom.curve.helix.Elicoide;
import org.geom.curve.helix.EnhancedElicoide;
import org.render.CurveRenderer2D;

import mvc.bezier.ControllerBezier2D;
import mvc.bezier.ViewCurveBezier2D;
import mvc.controller.Controller;
import mvc.elicoide.ControllerElicoide2D;
import mvc.elicoide.ModelElicoide;
import mvc.enhancedElicoide.ControllerEnhancedElicoide2D;
import mvc.enhancedElicoide.IModelComplexHelix;
import mvc.model.ModelCurve;
import mvc.view.ViewCurve;

public class BlockFactory {

	//-------------------------------------------------------------------------- elicoide

	public static GuiBlock getElicoideNormalBlock(ModelCurve e, Dimension viewDimension) {
		GuiBlock r = new GuiBlock(e);
		addViewController(r, e, viewDimension,
				ViewCurve.class, "elicoide x", CurveRenderer2D.X,
				ControllerElicoide2D.class, Elicoide.R);
		addViewController(r, e, viewDimension,
				ViewCurve.class, "elicoide y", CurveRenderer2D.Y,
				ControllerElicoide2D.class, Elicoide.K);
		addViewController(r, e, viewDimension,
				ViewCurve.class, "elicoide z", CurveRenderer2D.Z,
				ControllerElicoide2D.class, "");
		return r;
	}
	
	public static GuiBlock getElicoideSpecialBlock(ModelCurve curve, Dimension viewDimension) {
		GuiBlock r = new GuiBlock(curve);
		ModelElicoide e = ((IModelComplexHelix)curve).getElicoideModel();
		addViewControllerDifferentModel(r, e
				, viewDimension,
				ViewCurve.class, "elicoide x", CurveRenderer2D.X,
				curve,
				ControllerEnhancedElicoide2D.class, Elicoide.R);
		addViewControllerDifferentModel(r, e, viewDimension,
				ViewCurve.class, "elicoide y", CurveRenderer2D.Y,
				curve,
				ControllerEnhancedElicoide2D.class, Elicoide.K);

//		addViewControllerDifferentModel(r, e
//				, viewDimension,
//				ViewCurve.class, "elicoide x", CurveRenderer2D.X,
//				e,
//				ControllerElicoide2D.class, Elicoide.R);
//		addViewControllerDifferentModel(r, e, viewDimension,
//				ViewCurve.class, "elicoide y", CurveRenderer2D.Y,
//				e,
//				ControllerElicoide2D.class, Elicoide.K);

		//special controller
		ViewCurve v = new ViewCurve(e, 
				new CurveRenderer2D(CurveRenderer2D.Z), 
				viewDimension, "elicoide z");
		
		Controller c = new ControllerEnhancedElicoide2D(curve, v, EnhancedElicoide.U);
		
		r.addViewController(v, c);
		
		return r;
	}
	
	public static GuiBlock getBezierNormalBlock (ModelCurve b, Dimension viewDimension) {		
		GuiBlock r = new GuiBlock(b);

		addViewController(r, b, viewDimension,
				ViewCurveBezier2D.class, "bezier x", CurveRenderer2D.X,
				ControllerBezier2D.class, CurveRenderer2D.X);
		addViewController(r, b, viewDimension,
				ViewCurveBezier2D.class, "bezier y", CurveRenderer2D.Y,
				ControllerBezier2D.class, CurveRenderer2D.Y);
		addViewController(r, b, viewDimension,
				ViewCurveBezier2D.class, "bezier z", CurveRenderer2D.Z,
				ControllerBezier2D.class, CurveRenderer2D.Z);
		return r;
	}

	
	//-------------------------------------------------------------------------- dirty reflection
	
	private static void addViewController(GuiBlock r, ModelCurve m, 
			Dimension viewDimension, Class<?> viewClass, String title, 
			String rendererType,
			Class<?> controllerClass, String controllerParam) {		
		try {
			Constructor<?> k = viewClass.getDeclaredConstructors()[0];
			ViewCurve v = (ViewCurve) k.newInstance(m, new CurveRenderer2D(rendererType), viewDimension, title);
			
			k = controllerClass.getDeclaredConstructors()[0];
			Controller c = (Controller) k.newInstance(m, v, controllerParam);
			
			r.addViewController(v, c);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	private static void addViewControllerDifferentModel(
			GuiBlock r, ModelCurve modelForView, 
			Dimension viewDimension, Class<?> viewClass, String title, 
			String rendererType,
			ModelCurve modelForController,
			Class<?> controllerClass, String controllerParam) {		
		try {
			Constructor<?> k = viewClass.getDeclaredConstructors()[0];
			ViewCurve v = (ViewCurve) k.newInstance(modelForView, new CurveRenderer2D(rendererType), viewDimension, title);
			
			k = controllerClass.getDeclaredConstructors()[0];
			Controller c = (Controller) k.newInstance(modelForController, v, controllerParam);
			
			r.addViewController(v, c);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
